home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / gawk / gawk213s.zoo / gawk-src-2.13 / main.c < prev    next >
C/C++ Source or Header  |  1991-07-21  |  16KB  |  673 lines

  1. /*
  2.  * main.c -- Expression tree constructors and main program for gawk. 
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1986, 1988, 1989, 1991 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming Language.
  10.  * 
  11.  * GAWK is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 1, or (at your option)
  14.  * any later version.
  15.  * 
  16.  * GAWK is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GAWK; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "awk.h"
  27. #include "patchlevel.h"
  28.  
  29. static void usage P((void));
  30. static void copyleft P((void));
  31. static void cmdline_fs P((char *str));
  32. static void init_args P((int argc0, int argc, char *argv0, char **argv));
  33. static void init_vars P((void));
  34. static void pre_assign P((char *v));
  35. SIGTYPE catchsig P((int sig, int code));
  36. static void gawk_option P((char *optstr));
  37. static void nostalgia P((void));
  38.  
  39. /* These nodes store all the special variables AWK uses */
  40. NODE *FS_node, *NF_node, *RS_node, *NR_node;
  41. NODE *FILENAME_node, *OFS_node, *ORS_node, *OFMT_node;
  42. NODE *CONVFMT_node;
  43. NODE *FNR_node, *RLENGTH_node, *RSTART_node, *SUBSEP_node;
  44. NODE *ENVIRON_node, *IGNORECASE_node;
  45. NODE *ARGC_node, *ARGV_node;
  46. NODE *FIELDWIDTHS_node;
  47.  
  48. int NF;
  49. int NR;
  50. int FNR;
  51. int IGNORECASE;
  52. char *FS;
  53. char *RS;
  54. char *OFS;
  55. char *ORS;
  56. char *OFMT;
  57. char *CONVFMT;
  58.  
  59. /*
  60.  * The parse tree and field nodes are stored here.  Parse_end is a dummy item
  61.  * used to free up unneeded fields without freeing the program being run 
  62.  */
  63. int errcount = 0;    /* error counter, used by yyerror() */
  64.  
  65. /* The global null string */
  66. NODE *Nnull_string;
  67.  
  68. /* The name the program was invoked under, for error messages */
  69. const char *myname;
  70.  
  71. /* A block of AWK code to be run before running the program */
  72. NODE *begin_block = 0;
  73.  
  74. /* A block of AWK code to be run after the last input file */
  75. NODE *end_block = 0;
  76.  
  77. int exiting = 0;        /* Was an "exit" statement executed? */
  78. int exit_val = 0;        /* optional exit value */
  79.  
  80. #if defined(YYDEBUG) || defined(DEBUG)
  81. extern int yydebug;
  82. #endif
  83.  
  84. char **srcfiles = NULL;        /* source file name(s) */
  85. int numfiles = -1;        /* how many source files */
  86. char *cmdline_src = NULL;    /* if prog is on command line */
  87.  
  88. int strict = 0;            /* turn off gnu extensions */
  89. int do_posix = 0;        /* turn off gnu extensions and \x */
  90. int do_lint = 0;        /* provide warnings about questionable stuff */
  91.  
  92. int output_is_tty = 0;        /* control flushing of output */
  93.  
  94. extern char *version_string;    /* current version, for printing */
  95.  
  96. NODE *expression_value;
  97.  
  98. /*
  99.  * for strict to work, legal options must be first
  100.  *
  101.  * Unfortunately, -a and -e are orthogonal to -c.
  102.  *
  103.  * Note that after 2.13, c,a,e,C,D, and V go away.
  104.  */
  105. #ifdef DEBUG
  106. char awk_opts[] = "F:f:v:W:caeCVD";
  107. #else
  108. char awk_opts[] = "F:f:v:W:caeCV";
  109. #endif
  110.  
  111. int
  112. main(argc, argv)
  113. int argc;
  114. char **argv;
  115. {
  116.     int c;
  117.     extern int optind;
  118.     extern char *optarg;
  119.     int i;
  120.     int do_nostalgia;
  121.     int regex_mode = RE_SYNTAX_AWK;
  122.  
  123.     (void) signal(SIGFPE,  (SIGTYPE (*) P((int))) catchsig);
  124.     (void) signal(SIGSEGV, (SIGTYPE (*) P((int))) catchsig);
  125. #ifdef VMS
  126.     (void) signal(SIGBUS,  (SIGTYPE (*) P((int))) catchsig);
  127. #endif
  128.  
  129. #ifndef VMS
  130.     myname = basename(argv[0]);
  131. #else    /* VMS */
  132.     myname = strdup(basename(argv[0]));
  133.     argv[0] = (char *) myname;   /* strip path [prior to getopt()] */
  134.     vms_arg_fixup(&argc, &argv); /* emulate redirection, expand wildcards */
  135. #endif
  136.     if (argc < 2)
  137.         usage();
  138.  
  139.     /* remove sccs gunk */
  140.     if (strncmp(version_string, "@(#)", 4) == 0)
  141.         version_string += 4;
  142.  
  143.     /* initialize the null string */
  144.     Nnull_string = make_string("", 0);
  145.     Nnull_string->numbr = 0.0;
  146.     Nnull_string->type = Node_val;
  147.     Nnull_string->flags = (PERM|STR|STRING|NUM|NUMERIC|NUMBER);
  148.  
  149.     /* Set up the special variables */
  150.  
  151.     /*
  152.      * Note that this must be done BEFORE arg parsing else -F
  153.      * breaks horribly 
  154.      */
  155.     init_vars();
  156.  
  157.     /* worst case */
  158.     emalloc(srcfiles, char **, argc * sizeof(char *), "main");
  159.     srcfiles[0] = NULL;
  160.  
  161.     /* undocumented feature, inspired by nostalgia, and a T-shirt */
  162.     do_nostalgia = 0;
  163.     for (i = 1; i < argc && argv[i][0] == '-'; i++) {
  164.         if (argv[i][1] == '-')        /* -- */
  165.             break;
  166.         else if (argv[i][1] == 'c') {    /* compat not in next release */
  167.             do_nostalgia = 0;
  168.             break;
  169.         } else if (STREQ(&argv[i][1], "nostalgia"))
  170.             do_nostalgia = 1;
  171.             /* keep looping, in case -c after -nostalgia */
  172.     }
  173.     if (do_nostalgia) {
  174.         fprintf(stderr, "%s, %s\n",
  175.         "warning: option -nostalgia will go away in the next release",
  176.         "use -W nostalgia");
  177.         nostalgia();
  178.         /* NOTREACHED */
  179.     }
  180.  
  181.     while ((c = getopt (argc, argv, awk_opts)) != EOF) {
  182.         switch (c) {
  183. #ifdef DEBUG
  184.         case 'D':
  185.             fprintf(stderr,
  186. "warning: option -D will go away in the next release, use -W parsedebug\n");
  187.             gawk_option("parsedebug");
  188.             break;
  189. #endif
  190.  
  191.         case 'c':
  192.             fprintf(stderr,
  193.     "warning: option -c will go away in the next release, use -W compat\n");
  194.             gawk_option("compat");
  195.             break;
  196.  
  197.         case 'F':
  198.             cmdline_fs(optarg);
  199.             break;
  200.  
  201.         case 'f':
  202.             /*
  203.              * a la MKS awk, allow multiple -f options.
  204.              * this makes function libraries real easy.
  205.              * most of the magic is in the scanner.
  206.              */
  207.             srcfiles[++numfiles] = optarg;
  208.             break;
  209.  
  210.         case 'v':
  211.             pre_assign(optarg);
  212.             break;
  213.  
  214.         case 'V':
  215.             warning(
  216.         "option -V will go away in the next release, use -W version");
  217.             gawk_option("version");
  218.             break;
  219.  
  220.         case 'C':
  221.             warning(
  222.         "option -C will go away in the next release, use -W copyright");
  223.             gawk_option("copyright");
  224.             break;
  225.  
  226.         case 'a':    /* use old fashioned awk regexps */
  227.             warning("option -a will go away in the next release");
  228.             /*regex_mode = RE_SYNTAX_AWK;*/
  229.             break;
  230.  
  231.         case 'e':    /* use Posix style regexps */
  232.             warning("option -e will go away in the next release");
  233.             /*regex_mode = RE_SYNTAX_POSIX_AWK;*/
  234.             break;
  235.  
  236.         case 'W':       /* gawk specific options */
  237.             gawk_option(optarg);
  238.             break;
  239.  
  240.         case '?':
  241.         default:
  242.             /* getopt will print a message for us */
  243.             /* S5R4 awk ignores bad options and keeps going */
  244.             break;
  245.         }
  246.     }
  247.  
  248.     /* Tell the regex routines how they should work. . . */
  249.     (void) re_set_syntax(regex_mode);
  250.     regsyntax(regex_mode, 0);
  251.  
  252. #ifdef DEBUG
  253.     setbuf(stdout, (char *) NULL);    /* make debugging easier */
  254. #endif
  255.     if (isatty(fileno(stdout)))
  256.         output_is_tty = 1;
  257.     /* No -f option, use next arg */
  258.     /* write to temp file and save sourcefile name */
  259.     if (numfiles == -1) {
  260.         if (optind > argc - 1)    /* no args left */
  261.             usage();
  262.         cmdline_src = argv[optind];
  263.         optind++;
  264.     }
  265.     srcfiles[++numfiles] = NULL;
  266.     init_args(optind, argc, (char *) myname, argv);
  267.     (void) tokexpand();
  268.  
  269.     /* Read in the program */
  270.     if (yyparse() || errcount)
  271.         exit(1);
  272.  
  273.     /* Set up the field variables */
  274.     init_fields();
  275.  
  276.     if (begin_block)
  277.         (void) interpret(begin_block);
  278.     if (!exiting && (expression_value || end_block))
  279.         do_input();
  280.     if (end_block)
  281.         (void) interpret(end_block);
  282.     if (close_io() != 0 && exit_val == 0)
  283.         exit_val = 1;
  284.     exit(exit_val);        /* more portable */
  285.     return exit_val;    /* to suppress warnings */
  286. }
  287.  
  288. static void
  289. usage()
  290. {
  291.     char *opt1 = " -f progfile [--]";
  292.     char *opt2 = " [--] 'program'";
  293.     char *regops = " [-F fs] [-v var=val] [-W gawk-opts]";
  294.  
  295.     fprintf(stderr, "usage: %s%s%s file ...\n       %s%s%s file ...\n",
  296.         myname, regops, opt1, myname, regops, opt2);
  297.     exit(11);
  298. }
  299.  
  300. Regexp *
  301. mk_re_parse(s, ignorecase)
  302. char *s;
  303. int ignorecase;
  304. {
  305.     char *src;
  306.     register char *dest;
  307.     register int c;
  308.     int in_brack = 0;
  309.  
  310.     for (dest = src = s; *src != '\0';) {
  311.         if (*src == '\\') {
  312.             c = *++src;
  313.             switch (c) {
  314.             case '/':
  315.             case 'a':
  316.             case 'b':
  317.             case 'f':
  318.             case 'n':
  319.             case 'r':
  320.             case 't':
  321.             case 'v':
  322.             case 'x':
  323.             case '0':
  324.             case '1':
  325.             case '2':
  326.             case '3':
  327.             case '4':
  328.             case '5':
  329.             case '6':
  330.             case '7':
  331.                 c = parse_escape(&src);
  332.                 if (c < 0)
  333.                     cant_happen();
  334.                 *dest++ = (char)c;
  335.